﻿using System;
using System.Windows;

namespace Microsoft.Services.Clab.UI.Mvvmc.Presentation
{
    public class PropertySync
    {
        internal PropertySync(DependencyProperty viewDependencyProperty, string viewModelPropertyName)
        {
            if (viewDependencyProperty == null)
            {
                throw new ArgumentNullException("viewDependencyProperty");
            }

            if (string.IsNullOrEmpty(viewModelPropertyName))
            {
                throw new ArgumentNullException("viewModelPropertyName");
            }

            this.ViewDependencyProperty = new WeakReference(viewDependencyProperty);
            this.ViewModelPropertyName = viewModelPropertyName;
        }

        public WeakReference ViewDependencyProperty { get; private set; }
        public string ViewModelPropertyName { get; private set; }

        public bool IsUpdating { get; internal set; }

        public LockToken LockUpdate()
        {
            return new LockToken(this);
        }

        public class LockToken : IDisposable
        {
            private PropertySync mapping;

            internal LockToken(PropertySync mapping)
            {
                this.mapping = mapping;
                if (!mapping.IsUpdating)
                {
                    this.Acquired = true;
                    this.mapping.IsUpdating = true;
                }
                else
                {
                    this.Acquired = false;
                }
            }

            public bool Acquired { get; private set; }

            #region IDisposable Members

            ~LockToken()
            {
                Dispose(false);
            }

            public void Dispose()
            {
                this.Dispose(true);
            }

            private void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (this.Acquired)
                    {
                        this.mapping.IsUpdating = false;
                    }
                }
            }

            #endregion
        }
    }
}
